﻿using System;
using System.Collections.Generic;
using RayDen.Library.Components.SystemComponents;

namespace RayDen.RayEngine.Engines.ProgressivePhotonMapping
{
    public class PPMContext
    {
        private readonly object build_lock = new object();
        public int MaxHitPoints, PhotonMapPhotons, Width, Height;
        public IEyePointHashGrid Grid;
        protected internal List<PPMHitPoint> hitPoints;

        protected internal int photons;
        protected internal ulong TotalPhotons;

        public bool HitPointsGathered
        {
            get { return this.hitPoints.Count >= MaxHitPoints; }
        }

        public PPMContext()
        {
            hitPoints = new List<PPMHitPoint>(1000000);
        }

        public int PhotonsGathered
        {
            get { return photons; }
        }

        public bool Splat
        {
            get
            {
                return photons > PhotonMapPhotons;
            }
        }

        public void AddHitPoint(PPMHitPoint hp)
        {
            if (this.hitPoints.Count <= MaxHitPoints)
            {
                this.hitPoints.Add(hp);
#if VERBOSE
                if (hitPoints.Count % 1000 == 0)
                    Tracer.TraceLine("HitPoints -Collected {0} / Needed {1}", hitPoints.Count, MaxHitPoints);
#endif
            }
            else
            {
                if (Grid == null)
                {
                    lock (build_lock)
                    {
                        Tracer.TraceLine("Start building photons hashgrid");
                        Grid = new HashGrid(hitPoints, Width, Height);
                        Grid.ReHash();
                        Tracer.TraceLine("Complete!");
                    }
                }
            }

        }


        internal void IncreasePhoton()
        {
           // photons++;
        }

        internal void StoreFlux(float Alpha, ref Library.Core.Primitives.Point hitPoint, ref Library.Core.Primitives.Normal normal, Library.Core.Primitives.Vector wo, ref Library.Core.Primitives.RgbSpectrum ThroughtPut)
        {
            Grid.StoreFlux(Alpha, ref hitPoint, ref normal, wo, ref ThroughtPut);
            photons++;
#if VERBOSE
            if (photons % 1000 == 0)
                Tracer.TraceLine("#Photons  Collected {0}  Needed {1}", photons, PhotonMapPhotons);
#endif
        }

        public void ResetContext()
        {
            lock (build_lock)
            {
                hitPoints.Clear();
                TotalPhotons += (ulong)photons;
                photons = 0;
                Grid = null;
            }
        }

        internal void BuildGrid()
        {
            if (Grid == null)
            {
                lock (build_lock)
                {
                    Tracer.TraceLine("Start building photons hashgrid");
                    Grid = new HashGrid(hitPoints, Width, Height);
                    Tracer.TraceLine("Complete!");
                }
            }
        }
    }
}